

// 文件输入输出 I/O
// std_file_io

/*

文件输入输出 I/O

File 结构体表示一个被打开的文件（它装包了一个文件描述符），并赋予了针对底层文件的读和/或写能力。（原文：The File struct represents a file that has been opened (it wraps a file descriptor), and gives read and/or write access to the underlying file.）

由于在进行文件 I/O（输入/输出）操作时很多情形都可能出现错误，因此所有的 File 方法都返回 io::Result<T> 类型，这是 Result<T, io::Error> 的别名。

这使得所有 I/O 操作的失败都变成显式内容。借助这点，程序员可以看到所有的失败路径，并鼓励主动去处理这些情形。

*/

/*
打开文件 open

open 静态方法能够以只读模式（read-only mode）打开一个文件。

File 拥有一个资源，文件描述符（file descriptor），以及在文件丢弃时管理好关闭文件的操作。（原文：A File owns a resource, the file descriptor and takes care of closing the file when it is droped.）
*/

use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

pub fn test_fn_open() {
    // 给所需的文件创建一个路径
    let path = Path::new("hello.txt");
    let display = path.display();

    // 以只读方式打开路径，返回 `io::Result<File>`
    let mut file = match File::open(&path) {
        // `io::Error` 的 `description` 方法返回一个描述错误的字符串。
        Err(why) => panic!("couldn't open {}: {}", display,
                                                   why.description()),
        Ok(file) => file,
    };

    // 读取文件内容到一个字符串，返回 `io::Result<usize>`
    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("couldn't read {}: {}", display,
                                                   why.description()),
        Ok(_) => print!("{} contains:\n{}\n", display, s),
    }

    // `file` 离开作用域，并且 `hello.txt` 文件将被关闭。
}

/*
下面是预期成功的输出：

$ echo "Hello World!" > hello.txt
$ rustc open.rs && ./open
hello.txt contains:
Hello World!

（我们鼓励您在不同的失败条件下测试前面的例子：hello.txt 不存在，或 hello.txt 不可读，等等。）
*/

/*
创建文件 create

create 静态方法以只写模式（write-only mode）打开一个文件。若文件已经存在，则旧内容将被销毁。否则，将创建一个新文件。
*/

static LOREM_IPSUM: &'static str =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\r\n
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\r\n
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\r\n
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\r\n
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\r\n
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
";


pub fn test_fn_create() {
    let path = Path::new("out/lorem_ipsum.txt");
    let display = path.display();

    // 以只写模式打开文件，返回 `io::Result<File>`
    let mut file = match File::create(&path) {
        Err(why) => panic!("couldn't create {}: {}",
                           display,
                           why.description()),
        Ok(file) => file,
    };

    // 将 `LOREM_IPSUM` 字符串写进 `file`，返回 `io::Result<()>`
    match file.write_all(LOREM_IPSUM.as_bytes()) {
        Err(why) => {
            panic!("couldn't write to {}: {}", display,
                                               why.description())
        },
        Ok(_) => println!("successfully wrote to {}", display),
    }
}

/*
下面是预期成功的输出：

$ mkdir out
$ rustc create.rs && ./create
successfully wrote to out/lorem_ipsum.txt
$ cat out/lorem_ipsum.txt
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

（和前面例子一样，我们鼓励你在失败条件下测试这个例子。）

还有一个更通用的 open_mode 方法，这能够以其他方式来来打开文件，如：read+write（读+写），追加（append），等等。
*/

